import os
import random
import time
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.common.keys import Keys
from core.captcha_solver import CaptchaSolver as CS
from selenium.common.exceptions import ElementClickInterceptedException
class TaskExecutor:
    def __init__(self, driver, folder_path=None, upload_limit=10, task_type=1, ac=None):
        """
        初始化TaskExecutor对象。

        :param driver: 打开到指定页面的浏览器对象
        :param folder_path: 文档所在文件夹路径，默认为None
        :param upload_limit: 上传次数限制，默认为10
        :param task_type: 任务类型，1表示vip文档上传，2表示定产vip上传
        :param ac: API客户端，负责和服务器通讯，用于任务2
        """
        self.driver = driver
        self.folder_path = folder_path or self._default_folder_path(task_type)
        self.upload_limit = upload_limit
        self.error_num = 0  # 错误次数
        self.ac = ac
        self.task_able = True
        self.task_type = task_type

        if self.task_type == 1:
            self.upload_vip_file()
        elif self.task_type == 2:
            self.upload_vip2_file()

    def _default_folder_path(self, task_type):
        """
        返回默认的文件夹路径。

        :param task_type: 任务类型
        :return: 默认文件夹路径
        """
        folder_name = "vip_files" if task_type == 1 else "task_files"
        return os.path.join(os.getcwd(), folder_name)

    def upload_vip_file(self):
        """
        上传VIP文档任务。
        """
        print("========================================================================================")
        print(f"VIP文档任务开始，计划上传{self.upload_limit}次，文件目录为 {self.folder_path}")
        print("========================================================================================")
        files_list = self._get_files_list(self.folder_path)
        if not files_list:
            print("文件夹中没有找到文件，上传任务结束。")
            return

        random.shuffle(files_list)
        for count, file_path in enumerate(files_list, 1):
            print(f"----------开始上传第 {count} 个文档----------")
            if not self.upload_file(file_path):
                print("终止文件上传过程，请检查下原因。")
                break
            print(f"已完成 {count} 个文档上传")
            time.sleep(random.randint(5, 20))
            if count >= self.upload_limit:
                print(f"==========================================上传完成累计{count} 个==============================================")
                break

    def upload_vip2_file(self):
        """
        上传定产VIP文档任务。
        """
        i = 1
        for filename in os.listdir(self.folder_path):
            if i >= self.upload_limit:
                print("===========上传任务已完成==========")
                break
            if not self.task_able:
                print("===========今日任务已完成==========")
                break
            file_path = os.path.join(self.folder_path, filename)
            base_filename = os.path.splitext(filename)[0]
            titles = self.ac.get_data(endpoint="/api/wenku/titles/get_titles_list", title_name=base_filename, limitNum=1)
            if not titles:
                print(f"无法在数据库中找到相关任务：{filename}")
                continue

            data = titles[0]
            print(f"开始进行任务：{data['article_name']}")
            # 优化：返回1、2、3分别赋值，1为成功，2为失败，3为跳过
            res = self._process_vip2_task(data, file_path)
            if res == 2:
                break
            elif res == 3:
                continue
            print(f"===================已完成第{i}个任务====================")
            i += 1

    def _get_files_list(self, folder_path):
        """
        获取文件夹中的文件列表。

        :param folder_path: 文件夹路径
        :return: 文件列表
        """
        files_list = []
        for root, dirs, files in os.walk(folder_path):
            for file in files:
                files_list.append(os.path.join(root, file))
        return files_list

    def _process_vip2_task(self, data, file_path):
        """
        处理定产VIP任务。

        :param data: 任务数据--数据库中的那条数据
        :param filename: 文件名
        :return: 任务是否成功完成
        """
        err_num = 0
        while True:
            time.sleep(10)
            if not self.task_able:
                print("===========今日任务已完成==========")
                return 2
            if err_num >= 5:
                print("上传累计错误5次，结束任务")
                return 2
            # 如果找不到导航，则重试
            if not self._navigate_to_task_page(data):
                err_num += 1
                self.driver.refresh()
                continue

            if not self._upload_vip2_file(data, file_path):
                err_num += 1
                return False
            return True
        return False
    def _navigate_to_task_page(self, data):
        """
        导航到定产VIP任务页面。

        :param data: 任务数据
        :return: 是否成功导航
        """
        try:
            # containers = self.driver.find_elements(By.CSS_SELECTOR, '.privilege-item-container')
            # print(f"containers:{containers}")
            wait = WebDriverWait(self.driver, 10)  # 等待时间设置为10秒
            containers = wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, '.privilege-item-container')))
            # for container in containers:
            #     print(container.text)

            if data['article_type'] < 20:
                target_index = data['article_type'] + 2
                if target_index <= len(containers):
                    print("准备点击")
                    containers[target_index - 1].click()
            print(f"---切换到分类，分类标识：{data['article_type']}")
            time.sleep(10)

            pagination_input = WebDriverWait(self.driver, 20).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, 'div.pagination input[type=number]'))
            )
            pagination_input.clear()
            pagination_input.send_keys(int(data['page_number']) + 1)
            pagination_input.send_keys(Keys.ENTER)
            print(f"---定位到页面，页码：{data['page_number'] + 1}")
            time.sleep(3)
            return True
        except TimeoutException:
            print("导航到任务页面失败")
            return False

    def _upload_vip2_file(self, data, file_path):
        """
        上传定产VIP文件。

        :param data: 任务数据
        :param filename: 文件名
        :return: 是否成功上传
        """
        while True:
            try:
                doc_rows = self.driver.find_elements(By.CSS_SELECTOR, 'div.doc-wrapper div.doc-row')
                target_doc_row = doc_rows[data['page_sort_number'] - 1] if data['page_sort_number'] <= len(doc_rows) else None
                if not target_doc_row:
                    print("未找到对应的文档行")
                    return False

                title_span = target_doc_row.find_element(By.CSS_SELECTOR, '.title-line .doc-title')
                title_value = title_span.get_attribute('title')
                if title_value != data['article_name']:
                    print("应该是出错了，文档标题不对")
                    return False
                # time.sleep(1000)
                status_span = target_doc_row.find_element(By.CSS_SELECTOR, '.complete-status')
                # if 'none' not in status_span.get_attribute('style').lower():
                if status_span.is_displayed():
                    print("此任务已完成")
                    return False
                try:
                    file_input = target_doc_row.find_element(By.CSS_SELECTOR, '.file-selector-input') #input[type=file]
                    # 或者，获取并打印元素的outerHTML（包括元素本身的HTML）
                    # print("元素的outerHTML:", file_input.get_attribute('outerHTML'))
                except Exception:
                    self.task_able = False
                    print("未找到对应的上传表单，结束任务")
                    return False
                print("找到了文件的input")
                #模拟点击
                upload_botton = target_doc_row.find_element(By.CSS_SELECTOR, '.el-button')
                upload_botton.click()
                print("开始点击上传按钮")
                time.sleep(3)
                if not self.upload_file2(file_path, file_input):
                    self.driver.refresh()
                    time.sleep(10)
                    self._navigate_to_task_page(data)
                    return self._upload_vip2_file(data, file_path)
                return True
            except Exception as e:
                self.driver.save_screenshot('上传定产VIP文件失败.png')
                print(f"上传定产VIP文件失败：{e}")
                return False

    def upload_file(self, file_path):
        """
        上传文件。

        :param file_path: 文件路径
        :return: 是否成功上传
        """
        if self.error_num == 5:
            print("连续出错5次,请分析原因")
            return False

        try:
            file_input = WebDriverWait(self.driver, 20).until(
                EC.presence_of_element_located((By.CSS_SELECTOR, ".file-selector-input"))
            )
        except TimeoutException:
            self.driver.save_screenshot('无法上传查看.png')
            print("今日已达上限")
            return False

        # file_input.send_keys(file_path)#upload-doc#upload-doc > div
        # add_button = self.driver.get_element_by_id("upload-doc")
        # add_button = self.driver.find_element(By.ID, 'upload-doc')
        # add_button.click()
        try:
            file_input.send_keys(file_path)
        except Exception as e:
            print(f"send_keys失败：{e}")
            print("元素的outerHTML:", file_input.get_attribute('outerHTML'))
            self.driver.save_screenshot('send_keys失败.png')
            self.error_num += 1
            return False
        time.sleep(5)

        if "seccaptcha.baidu.com" in self.driver.current_url:
            print("==============================开始处理验证码==============================")
            self.handle_captcha()
            return self.upload_file(file_path)

        try:
            WebDriverWait(self.driver, 30).until(
                EC.invisibility_of_element_located((By.CSS_SELECTOR, ".el-loading-mask"))
            )
        except TimeoutException:
            print("等待遮罩层消失超时，已保存错误截图，即将重试。")
            self.driver.save_screenshot('一直显示上传中.png')
            self.error_num += 1
            return self.upload_file(file_path)
        # 选择vip文档
        # try:
        #     radio_select = WebDriverWait(self.driver, 300).until(
        #         EC.element_to_be_clickable((By.CSS_SELECTOR, ".el-radio:nth-child(3) .el-radio__inner"))
        #     )
        #     time.sleep(1)
        #     radio_select.click()
        # except TimeoutException:
        #     print("文件检查无效，请核实")
        #     self.driver.save_screenshot('文件检查无效.png')
        #     self.error_num += 1
        #     self.driver.refresh()
        #     return False
        try:
            radio_select = WebDriverWait(self.driver, 30).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, ".el-radio:nth-child(3) .el-radio__inner"))
            )
            self.driver.execute_script("arguments[0].scrollIntoView();", radio_select)
            time.sleep(1)
            radio_select.click()
        except TimeoutException:
            print("文件检查无效，请核实")
            self.driver.save_screenshot('文件检查无效.png')
            self.error_num += 1
            self.driver.refresh()
            return False
        except ElementClickInterceptedException:
            print("元素被遮挡，尝试通过JavaScript点击")
            self.driver.save_screenshot('元素被遮挡尝试通过JavaScript点击.png')
            self.driver.execute_script("arguments[0].click();", radio_select)

        if not self._submit_upload_form(file_path):
            return self.upload_file(file_path)
        return True

    def upload_file2(self, file_path, file_input):
        """
        上传定产VIP文件。

        :param file_path: 文件路径
        :param file_input: 文件输入框
        :return: 是否成功上传
        """
        # print(file_path)
        # print(file_input)
        time.sleep(3)
        # print("元素的outerHTML:", file_input.get_attribute('outerHTML'))
        file_input.send_keys(file_path)

        time.sleep(5)
        # print("--------------------------------正在等待手动确认--------------------------------")
        # time.sleep(600)
        if "seccaptcha.baidu.com" in self.driver.current_url:
            print("==============================开始处理验证码==============================")
            self.handle_captcha()
            return False

        try:
            WebDriverWait(self.driver, 30).until(
                EC.invisibility_of_element_located((By.CSS_SELECTOR, ".el-loading-mask"))
            )
        except TimeoutException:
            print("等待遮罩层消失超时，已保存错误截图，即将重试。")
            self.driver.save_screenshot('一直显示上传中.png')
            return False
        # time.sleep(100)
        time.sleep(10)
        if not self._submit_upload_form(file_path):
            return False
        return True

    def _submit_upload_form(self, file_path):
        """
        提交上传表单。

        :param file_path: 文件路径
        :return: 是否成功提交
        """
        if "seccaptcha.baidu.com" in self.driver.current_url:
            print("==============================开始处理验证码==============================")
            self.handle_captcha()
            return False

        try:
            submit_button = WebDriverWait(self.driver, 20).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, ".doc-upload-btn-bar > .el-button > span"))
            )
            print("确认上传按钮可以用了，现在截图备查")
            self.driver.save_screenshot('确认上传按钮可以用了.png')
            submit_button.click()
            time.sleep(2)
            self.driver.save_screenshot('确认上传按钮可以用了1.png')
        except TimeoutException:
            print("确认提交按钮无法点击，请查看截图")
            self.driver.save_screenshot('确认提交按钮无法点击.png')
            self.error_num += 1
            time.sleep(30)
            self.driver.refresh()
            return False

        try:
            success_dialog = WebDriverWait(self.driver, 20).until(
                EC.presence_of_element_located((By.CSS_SELECTOR, ".upload-dialog-footer > .el-button"))
            )
            success_dialog.click()
            os.remove(file_path)
            print(f"{file_path} 上传成功并已删除")
        except TimeoutException:
            print(f"{file_path}上传失败")
            self.driver.save_screenshot('确认上传后出错.png')
            self.error_num += 1
            time.sleep(60)
            self.driver.refresh()
            return False
        return True

    def download_vip_file(self, docs, num=0):
        random.shuffle(docs)
        # 循环访问页面并下载
        download_count = 0  # 已下载的文档数量
        max_download_count = num  # 最大下载次数限制
        for doc in docs:
            if download_count >= max_download_count:
                print("已达到最大下载次数，结束下载")
                break
            if doc['doc_status'] != 2:
                continue
            doc_id = doc['doc_id']
            if doc['doc_status'] != 2:
                continue
            timestamp = int(time.time() * 1000)  # 获取13位时间戳?{timestamp}
            url = f'https://wenku.baidu.com/view/{doc_id}.html?_wkts_={timestamp}'
            self.driver.get(url)
            time.sleep(5)
            if "seccaptcha.baidu.com" in self.driver.current_url:
                print("出现了验证码...")
                self.handle_captcha()
            time.sleep(5)
            try:
                download_button = self.driver.find_element(By.CSS_SELECTOR, 'div.drop-down + .btn-normal')
                print(download_button)
                print(download_button.text)
                if '单篇下载' in download_button.text:
                    download_button.click()
                    print(f"第{download_count + 1}个VIP文档下载成功")
                    download_count += 1
                else:
                    if '重新下载' in download_button.text:
                        print(f"文档 {doc_id} 已经下载过")
            except Exception as e:
                print(f"文档 {doc_id} 下载失败: {e}")
            time.sleep(10)  # 等待3秒再进行下一个下载
    def handle_captcha(self):
        """
        处理验证码。
        """
        CS(self.driver)
        return

if __name__ == "__main__":
    # 示例代码
    # driver = ...  # 初始化浏览器对象
    # TaskExecutor(driver)
    print(111)
